

public class Percolation {
	private static final int CLOSED = 0;
	private static final int OPEN = 1;
	
	private WeightedQuickUnionUF uf;
	private int[][] grid;
	private int size = 0;
	
	public Percolation(int N) {              // create N-by-N grid, with all sites blocked
		
		size = N;
		uf = new WeightedQuickUnionUF(size*size+2);
		grid = new int[size][size];
		
		for (int x = 0; x < size; x++)
			for (int y = 0; y < size; y++)
				grid[x][y] = CLOSED;
		
		
	}
	
	public void open(int i, int j) {         // open site (row i, column j) if it is not already
		if (i < 1 || i > size || j < 1 || j > size)
			throw new IndexOutOfBoundsException();
		
		
		if (i != 1 && isOpen(i-1, j)) // covers up
			uf.union((i-2)*size + j, (i-1)*size + j);
		
		if (j != 1 && isOpen(i, j-1)) // covers left
			uf.union((i-1)*size + j-1, (i-1)*size + j);
		
		if (i != size && isOpen(i+1, j)) // covers down
			uf.union((i)*size + j, (i-1)*size + j);
		
		if (j != size && isOpen(i, j+1)) // covers right
			uf.union((i-1)*size + j+1, (i-1)*size + j);
		
		if (i == 1)
			uf.union(0, (i-1)*size + j);

		if (i == size)
			uf.union(size*size+1, (i-1)*size + j);

		grid[i-1][j-1] = OPEN;
	}
	
	public boolean isOpen(int i, int j) {   // is site (row i, column j) open?
		if (i < 1 || i > size || j < 1 || j > size)
			throw new IndexOutOfBoundsException();

		if (grid[i-1][j-1] >= OPEN)
			return true;
		
		return false;
	}
	
	public boolean isFull(int i, int j) {   // is site (row i, column j) full?
		if (i < 1 || i > size || j < 1 || j > size)
			throw new IndexOutOfBoundsException();
		
		if (uf.connected((i-1)*size + j, 0) && !uf.connected((i-1)*size + j, size*size+1))
			return true;
		
		return false;
	}
	
	public boolean percolates() {           // does the system percolate?
		
		if (uf.connected(0, size*size+1))
			return true;
					
		return false;
	}
}
